/***********************************************************************
    filename:   hgeWindowRenderer.h
    created:    Jan 11 2006
    author:     Tomas Lindquist Olsen

    purpose:    Defines interface for the WindowRenderer base class
*************************************************************************/

#ifndef _HgeWindowRenderer_h_
#define _HgeWindowRenderer_h_

#include "hgeGuiWindow.h"
#include "hgeGuiProperty.h"
#include <vector>

#if defined(_MSC_VER)
#   pragma warning(push)
#   pragma warning(disable : 4251)
#endif


/*!
\brief
    Base-class for the assignable WindowRenderer object
*/
class WindowRenderer
{
public:
    /*************************************************************************
        Constructor / Destructor
    **************************************************************************/
    /*!
    \brief
        Constructor

    \param name
        Factory type name

    \param class_name
        The name of a widget class that is to be the minimum requirement for
        this window renderer.
    */
    WindowRenderer(const String& name, const String& class_name="Window");

    /*!
    \brief
        Destructor
    */
    virtual ~WindowRenderer();

    /*************************************************************************
        Public interface
    **************************************************************************/
    /*!
    \brief
        Populate render cache.

        This method must be implemented by all window renderers and should
        perform the rendering operations needed for this widget.
        Normally using the Falagard API...
    */
    virtual void render() = 0;

    /*!
    \brief
        Returns the factory type name of this window renderer.
    */
    const String& getName() const   {return d_name;}

    /*!
    \brief
        Get the window this windowrenderer is attached to.
    */
    Window* getWindow() const       {return d_window;}

    /*!
    \brief
        Get the "minimum" Window class this renderer requires
    */
    const String& getClass() const  {return d_class;}

    /*!
    \brief
        Get unclipped inner rectangle that our window should return from its
        member function with the same name.
    */
    virtual hgeRect getUnclippedInnerRect() const;

    /*!
    \brief
        Method called to perform extended laying out of the window's attached
        child windows.
    */
    virtual void performChildWindowLayout() {}

    /*!
    \brief
        update the RenderingContext as needed for our window.  This is normally
        invoked via our window's member function with the same name.
    */
    virtual void getRenderingContext(RenderingContext& ctx) const;

    //! perform any time based updates for this WindowRenderer.
    virtual void update(float /*elapsed*/) {}

protected:
    /*************************************************************************
        Implementation methods
    **************************************************************************/
    /*!
    \brief
        Register a property class that will be properly managed by this window
        renderer.

    \param property
        Pointer to a static Property object that will be added to the target
        window.
    */
    void registerProperty(Property* property);

    /*!
    \brief
        Handler called when this windowrenderer is attached to a window
    */
    virtual void onAttach();

    /*!
    \brief
        Handler called when this windowrenderer is detached from its window
    */
    virtual void onDetach();

    /*!
    \brief
        Handler called when a Look'N'Feel is assigned to our window.
    */
    virtual void onLookNFeelAssigned() {}

    /*!
    \brief
        Handler called when a Look'N'Feel is removed/unassigned from our window.
    */
    virtual void onLookNFeelUnassigned() {}

    void operator=(const WindowRenderer&) {}

    /*************************************************************************
        Implementation data
    **************************************************************************/
    Window* d_window;       //!< Pointer to the window this windowrenderer is assigned to.
    const String d_name;    //!< Name of the factory type used to create this window renderer.
    const String d_class;   //!< Name of the widget class that is the "minimum" requirement.

    typedef std::vector<Property*> PropertyList;
    PropertyList d_properties;  //!< The list of properties that this windowrenderer will be handling.

    // Window is friend so it can manipulate our 'd_window' member directly.
    // We don't want users fiddling with this so no public interface.
    friend class Window;
};

class WindowRendererFactory
{
public:
	WindowRendererFactory(const String& name) : d_factoryName(name) {}
	virtual ~WindowRendererFactory() {}
	const String& getName() const {return d_factoryName;}
	virtual WindowRenderer* create() = 0;
	virtual void destroy(WindowRenderer* wr) = 0;

protected:
	String d_factoryName;   //!< Our factory type name.
};


template <typename T>
class TplWindowRendererFactory : public WindowRendererFactory
{
public:
	//! Default constructor.
	TplWindowRendererFactory();

	// Implement WindowRendererFactory interface
	WindowRenderer* create();
	void destroy(WindowRenderer* wr);
};

//----------------------------------------------------------------------------//
template <typename T>
TplWindowRendererFactory<T>::TplWindowRendererFactory() :
WindowRendererFactory(T::TypeName)
{
}

//----------------------------------------------------------------------------//
template <typename T>
WindowRenderer* TplWindowRendererFactory<T>::create()
{
	return new T(T::TypeName);
}

//----------------------------------------------------------------------------//
template <typename T>
void TplWindowRendererFactory<T>::destroy(WindowRenderer* wr)
{
	delete wr;
}

#if defined(_MSC_VER)
#   pragma warning(pop)
#endif

#endif // _HgeWindowRenderer_h_
